package com.handa.documentManager.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.handa.common.config.SnowflakeConfig;
import com.handa.common.entity.Response;
import com.handa.documentManager.entity.DO.OnlyofficeFileInfoDO;
import com.handa.documentManager.entity.Enum.OnlyOfficeCallBackStatus;
import com.handa.documentManager.entity.VO.GenerateOfficeConfigParamVO;
import com.handa.documentManager.service.IOnlyofficeFileInfoService;
import com.handa.documentManager.service.OnlyOfficeService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;

@RestController
@Slf4j
@RequestMapping("/documentManager/onlyoffice")
public class OnlyOfficeController {

    @Resource
    private MinioClient minioClient;

    @Resource
    private OnlyOfficeService onlyOfficeService;

    @Resource
    private IOnlyofficeFileInfoService onlyofficeFileInfoService;

    @Resource
    private SnowflakeConfig snowflakeConfig;

    @Value("${onlyOffice.server.url}")
    private String serverEndpoint;

    @GetMapping("/server-end-point")
    public Response<String> getEndPoint() {

        return Response.success(serverEndpoint);
    }

    // 生成 OnlyOffice 编辑配置
    @PostMapping("/config")
    public Response<String> generateConfig(@RequestBody GenerateOfficeConfigParamVO paramVO) {

        return Response.success(onlyOfficeService.generateConfig(paramVO));
    }

    @RequestMapping("/callback")
    public String callback(@RequestParam("fileName") String fileName,
                           @RequestParam(value = "path", required = false) String path,
                           @RequestParam(value = "bucket", required = false) String bucket,
                           @RequestParam(value = "userId", required = false) String userId,
                           HttpServletRequest request,
                           HttpServletResponse response) throws IOException {

        String fullPath = path + fileName;
        log.info("fullPath: " + fullPath);

        Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");

        String body = scanner.hasNext() ? scanner.next() : "";

        JSONObject jsonObj = JSONObject.parseObject(body);
        if (Objects.isNull(jsonObj)) {
            return "{\"error\":0}";
        }
        log.info("onlyOffice 传入 jsonObj:  --------- \n" + jsonObj);
        int status = (int) jsonObj.get("status");
        log.info("当前文档状态： " + status);
        if (status == OnlyOfficeCallBackStatus.READY_TO_SAVE.getCode() ||
                status == OnlyOfficeCallBackStatus.SAVE.getCode()) {
            String downloadUri = (String) jsonObj.get("url");

            URL url = new URL(downloadUri);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            InputStream stream = connection.getInputStream();

            //***** 最后一个用户关闭文档后10s后触发 *****
            if (status == OnlyOfficeCallBackStatus.READY_TO_SAVE.getCode()) {

                QueryWrapper<OnlyofficeFileInfoDO> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("bucket", bucket);
                queryWrapper.eq("absolute_path", fullPath);
                List<OnlyofficeFileInfoDO> list = onlyofficeFileInfoService.list(queryWrapper);

                OnlyofficeFileInfoDO onlyofficeFileInfoDO = new OnlyofficeFileInfoDO();
                onlyofficeFileInfoDO.setFileKey(onlyOfficeService.getKey(fullPath) + '_' + snowflakeConfig.snowflakeId());
                onlyofficeFileInfoDO.setAbsolutePath(fullPath);
                onlyofficeFileInfoDO.setUpdateTime(new Date());

                if (CollectionUtils.isNotEmpty(list)) {
                    onlyofficeFileInfoService.update(onlyofficeFileInfoDO, queryWrapper);
                } else {
                    onlyofficeFileInfoDO.setId(snowflakeConfig.snowflakeId());
                    onlyofficeFileInfoDO.setBucket(bucket);
                    onlyofficeFileInfoService.save(onlyofficeFileInfoDO);
                }
            }

            try {
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(bucket)
                                .object(fullPath)
                                .stream(stream, -1, 10485760) // 10MB 分片
                                .build());
                log.info("尝试保存到Minio 结束无报错");


            } catch (ErrorResponseException e) {
                throw new RuntimeException(e);
            } catch (InsufficientDataException e) {
                throw new RuntimeException(e);
            } catch (InternalException e) {
                throw new RuntimeException(e);
            } catch (InvalidKeyException e) {
                throw new RuntimeException(e);
            } catch (InvalidResponseException e) {
                throw new RuntimeException(e);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            } catch (ServerException e) {
                throw new RuntimeException(e);
            } catch (XmlParserException e) {
                throw new RuntimeException(e);
            }

            connection.disconnect();
        }
        return "{\"error\":0}";
    }

}